SD 卡是一種非易失性記憶體卡,於 1999 年由松下(Panasonic)、東芝(Toshiba)和 SanDisk 聯合開發。SD 卡廣泛應用於數位相機、行動電話、手持式裝置、以及其他儲存設備中。它們通常具有不同的容量和速度等級,從幾百 MB 到數 TB 不等,並且有標準大小、miniSD 和 microSD 等不同的形狀尺寸。
MicroSD 卡是 SD 卡的縮小版本,於 2005 年由 SanDisk推出。它被設計用於更小型的設備如智慧型手機、行車記錄器和行動裝置。MicroSD 卡的容量範圍與 SD 卡相似,但由於其小巧的尺寸在現代的行動裝置中非常受歡迎。
根據 Wiki 維基百科 SD_Card#Transfer_modes 的資料:
請參考下方的接腳對照表:
接線名稱 | 玩學機的接腳 | 對應GPIO |
---|---|---|
VCC | VUSB 第1腳 | |
GND | GND 第2腳 | |
CS | IO5 第5腳 | 5 |
MISO | IO19 第7腳 | 19 |
CK | IO18 第8腳 | 18 |
MOSI | IO23 第10腳 | 23 |
早期 ESP32 的 MicroPython 韌體沒有內建 SDcard 的驅動程式,只有 PyBoard 的硬體設計有內含一個 SD讀卡器。因此需要額外下載 sdcard.py 的驅動程式。您可以參考
請將 https://github.com/CoderDojoTC/micropython/blob/main/src/sound/sdcard.py
現在玩學機內建的 MicroPython 1.23 版本,machine 模組內已經有 sdcard 的驅動程式,相關資訊請參考
SD 卡是一種很常見的小型可移除存儲媒體,大小和形狀有很多種變化。除了 SD 卡之外,還有叫做 MMC 卡的類似設備,eMMC 則是專門設計來內嵌在其他系統中的存儲裝置。雖然它們的用途和外觀有些不同,但它們之間使用的通訊協定很類似,所以在 MicroPython 裡,它們都用同一個類別 machine.SDCard 來處理。
SD 和 MMC 卡可以用不同的 bus width 來存取。如果用 1-bit 的方式來讀取,它們可以透過 SPI 協定來傳輸資料。不同的 MicroPython 硬體平台可能支援不同的傳輸頻寬或接腳設定,但大部分硬體都有一個預設的設定值,只要不傳任何參數,創建物件時會自動使用預設的卡槽或引腳。
ESP32 提供了兩個 SD/MMC 硬體通道,也支援透過兩個 SPI 埠來讀取 SD 卡。所以當你在設置 SD 卡時,可以選擇的 slot 參數值範圍是 0 到 3。
import os
from machine import Pin, SoftSPI
from sdcard import SDCard
# MISO GPIO19 PIN 7
# MOSI GPIO23 PIN 10
# CS GPIO5 PIN5 ChipSelect
# SCK GPIO18 PIN 8 CLOCK VSPI CLK
# 預設設定
spisd = SoftSPI(2, miso=Pin(19), mosi=Pin(23), sck=Pin(18))
sd = SDCard(spisd, Pin(5))
# 01. 印出 /lib/ 檔案清單
print('/lib/: {}'.format(os.listdir('lib')))
程式執行的結果:
/lib/: ['esp32_i2c_1602lcd.py', 'lcd_api.py', 'max7219.py', 'pico_i2c_lcd.py', 'sdcard.py', 'uQR.py']
我們拿一片有裝樹梅派作業系統的 32GB 記憶卡來做測試,看看能否直接讀取到一些資料?
import os
from machine import Pin, SoftSPI
from sdcard import SDCard
spisd = SoftSPI(2, miso=Pin(19), mosi=Pin(23), sck=Pin(18))
sd = SDCard(spisd, Pin(5))
# 02. 掛載 SDCard
vfs = os.VfsFat(sd)
os.mount(vfs, '/sd')
os.chdir('sd')
print('SD 卡的根目錄:{}'.format(os.listdir()))
print('===================================================')
執行結果:
SD 卡的根目錄:['COPYING.linux', 'LICENCE.broadcom', 'bcm2708-rpi-b-plus.dtb', 'bcm2708-rpi-b.dtb', 'bcm2709-rpi-2-b.dtb', 'bootcode.bin', 'cmdline.txt', 'fixup.dat', 'fixup_cd.dat', 'fixup_db.dat', 'fixup_x.dat', 'kernel.img', 'kernel7.img', 'overlays', 'start.elf', 'start_cd.elf', 'start_db.elf', 'start_x.elf', 'issue.txt', 'LICENSE.oracle', '._.Trashes', '.Trashes', 'cmdline.0.txt', '.TemporaryItems', '._.TemporaryItems', 'config.txt', '._config.txt']
# 03. 開啟 cmdline.txt 檔案,查看裡面內容
vfs = os.VfsFat(sd)
os.mount(vfs, '/sd')
os.chdir('sd')
f = open('cmdline.txt', 'r')
print('cmdline.txt 的檔案內容:')
print('===========================================')
print(f.read())
f.close()
print('===========================================')
執行結果:
cmdline.txt 的檔案內容:
===========================================
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
===========================================
# 04. 建立一個檔案並增加內容:
vfs = os.VfsFat(sd)
os.mount(vfs, '/sd')
os.chdir('sd')
f = open('WiFiBoyFiles.txt', 'w')
f.write('Hello, WiFiBoy!')
f.close()
vfs = os.VfsFat(sd)
os.mount(vfs, '/sd')
os.chdir('sd')
f = open('WiFiBoyFiles.txt', 'a')
f.write('參加 2024 ITHome 鐵人賽!')
f.close()